package com.zhangzhan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhangzhan.annotation.SystemLog;
import com.zhangzhan.domain.commcon.ResponseResult;
import com.zhangzhan.domain.dto.*;
import com.zhangzhan.domain.entity.Role;
import com.zhangzhan.domain.entity.User;
import com.zhangzhan.domain.entity.UserRole;
import com.zhangzhan.domain.enums.AppHttpCodeEnum;
import com.zhangzhan.domain.vo.PageVO;
import com.zhangzhan.domain.vo.SelectUserVO;
import com.zhangzhan.domain.vo.UpdateUserRoleVO;
import com.zhangzhan.domain.vo.UserInfoVo;
import com.zhangzhan.exception.MySystemException;
import com.zhangzhan.mapper.UserMapper;
import com.zhangzhan.service.RoleService;
import com.zhangzhan.service.UserRoleService;
import com.zhangzhan.service.UserService;
import com.zhangzhan.utils.BeanCopyUtils;
import com.zhangzhan.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 用户表(User)表服务实现类
 *
 * @author makejava
 * @since 2022-09-19 21:28:36
 */
@Service("userService")
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserService usrService;


    /**
     * @param
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @description 查询用户信息
     * @author 31115
     * @date 2022/12/3 16:38
     */
    @Override
    public ResponseResult selectUserInfo() {

        //判断id是否为空
        Long id = SecurityUtils.getUserId();
        //根据id查询用户信息
        User user = getById(id);
        //封装成vo类 并返回
        UserInfoVo vo = BeanCopyUtils.beanCopyUtils(user, UserInfoVo.class);
        return ResponseResult.okResult(vo);
    }

    /**
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @description 修改用户信息
     * @author 31115
     * @date 2022/12/4 13:26
     */
    @Override
    @SystemLog(BusinessName = "修改更新用户信息")
    public ResponseResult putUserInfo(UserInfoVo userInfoVo) {
        if (userInfoVo == null) {
            return ResponseResult.errorResult(403, "用户信息为空");
        }

        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(User::getId, userInfoVo.getId());
        wrapper.set(User::getAvatar, userInfoVo.getAvatar());
        wrapper.set(User::getEmail, userInfoVo.getEmail());
        wrapper.set(User::getNickName, userInfoVo.getNickName());
        wrapper.set(User::getSex, userInfoVo.getSex());
        update(wrapper);

        return ResponseResult.okResult();
    }

    /**
     * @param user
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @description 注册
     * @author 31115
     * @date 2022/12/4 16:19
     */
    @Override
    public ResponseResult saveRegister(User user) {
        //对数据进行非空判断
        if (!StringUtils.hasText(user.getUserName())) {
            throw new MySystemException(AppHttpCodeEnum.USERNAME_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getPassword())) {
            throw new MySystemException(AppHttpCodeEnum.PASSWORD_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getEmail())) {
            throw new MySystemException(AppHttpCodeEnum.EMAIL_NOT_NULL);
        }
        if (!StringUtils.hasText(user.getNickName())) {
            throw new MySystemException(AppHttpCodeEnum.NICKNAME_NOT_NULL);
        }
        //对数据进行是否存在的判断
        if (userNameExist(user.getUserName())) {
            throw new MySystemException(AppHttpCodeEnum.USERNAME_EXIST);
        }
        if (nickNameExist(user.getNickName())) {
            throw new MySystemException(AppHttpCodeEnum.NICKNAME_EXIST);
        }
        //...
        //对密码进行加密
        String encodePassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodePassword);
        //存入数据库
        save(user);

        return ResponseResult.okResult();
    }

    private boolean nickNameExist(String nickName) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getNickName, nickName);
        int count = count(lambdaQueryWrapper);
        return count > 0;
    }

    private boolean userNameExist(String userName) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUserName, userName);
        int count = count(lambdaQueryWrapper);
        return count > 0;
    }

    private boolean passWordExist(String passWord) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getPassword, passWord);
        int count = count(lambdaQueryWrapper);
        return count > 0;
    }

    private boolean emailExist(String email) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getEmail, email);
        int count = count(lambdaQueryWrapper);
        return count > 0;
    }



    /**
     * @param pageNum
     * @param pageSize
     * @param pageUserDto
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @description 分页查询
     * @author 31115
     * @date 2022/12/8 8:48
     */
    @Override
    public ResponseResult<PageVO> userPage(Integer pageNum, Integer pageSize, PageUserDto pageUserDto) {

        Page<User> userPage = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.hasText(pageUserDto.getUserName()), User::getUserName, pageUserDto.getUserName())
                .eq(StringUtils.hasText(pageUserDto.getPhonenumber()), User::getPhonenumber, pageUserDto.getPhonenumber())
                .eq(StringUtils.hasText(pageUserDto.getStatus()), User::getStatus, pageUserDto.getStatus());

        page(userPage, wrapper);

        List<User> users = null;
        users = userPage.getRecords();

        return ResponseResult.okResult(new PageVO(users, userPage.getTotal()));
    }

    /**
     * @param dto
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @description 新增用户
     * @author 31115
     * @date 2022/12/8 9:48
     */
    @Override
    public ResponseResult saveUser(SaveUserDto dto) {
        //对字段进行校验
        if (!StringUtils.hasText(dto.getNickName())) {
            return ResponseResult.errorResult(500, "必须填写昵称");
        }
        if (!StringUtils.hasText(dto.getUserName())) {
            return ResponseResult.errorResult(500, "必须填写用户名");
        }
        if (!StringUtils.hasText(dto.getPassword())) {
            return ResponseResult.errorResult(500, "必须填写密码");
        }

        if (userNameExist(dto.getUserName())){
            return ResponseResult.errorResult(500, "用户名已存在");
        }
        if (nickNameExist(dto.getNickName())){
            return ResponseResult.errorResult(500, "用户昵称已存在");
        }
        if (passWordExist(dto.getPassword())){
            return ResponseResult.errorResult(500, "手机号已存在");
        }
        if (emailExist(dto.getEmail())){
            return ResponseResult.errorResult(500, "邮箱以存在");
        }

        //新增
        User user = BeanCopyUtils.beanCopyUtils(dto, User.class);
        //加密
        String encode = passwordEncoder.encode(user.getPassword());
        user.setPassword(encode);
        save(user);

        //新增用户角色中间表
        List<Long> roleIds = dto.getRoleIds();
        List<UserRole> userRoleList = roleIds.stream()
                .map(new Function<Long, UserRole>() {
                    @Override
                    public UserRole apply(Long roleId) {
                        UserRole userRole = new UserRole();
                        userRole.setRoleId(roleId);
                        userRole.setUserId(user.getId());
                        return userRole;
                    }
                }).collect(Collectors.toList());
        userRoleService.saveBatch(userRoleList);

        return ResponseResult.okResult();
    }

    /**
     * @description 批量删除
     * @param ids
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @author 31115
     * @date 2022/12/8 10:13
     */
    @Override
    public ResponseResult deleteByIds(Long[] ids) {
        List<Long> idList = Arrays.asList(ids);
        User user = new User();
        for (Long id : idList) {
            LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(User::getId,id)
                    .set(User::getDelFlag,"1");
            update(user,wrapper);
        }
        return ResponseResult.okResult();
    }

    /**
     * @description 根据id查询用户信息回显接口
     * @param id
     * @return com.zhangzhan.domain.commcon.ResponseResult<com.zhangzhan.domain.vo.UpdateUserRoleVO>
     * @author 31115
     * @date 2022/12/8 10:34
     */
    @Override
    public ResponseResult<UpdateUserRoleVO> selectById(Long id) {
        //查出用户所关联的角色id
        LambdaUpdateWrapper<UserRole> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(UserRole::getUserId,id);
        List<UserRole> userRoles = userRoleService.list(wrapper);
        List<Long> roleIds = userRoles.stream()
                .map(userRole -> {
                    Long roleId = userRole.getRoleId();
                    return roleId;
                }).collect(Collectors.toList());

        //查出所有角色属性
        List<Role> roles = roleService.list();
        List<SelectUserVO> roleVo = BeanCopyUtils.beanCopyUtil(roles, SelectUserVO.class);
        //查出用户信息
        User user = usrService.getById(id);
        UserDto userDto = BeanCopyUtils.beanCopyUtils(user, UserDto.class);
        //封装信息
        UpdateUserRoleVO updateUserRoleVO = new UpdateUserRoleVO();
        updateUserRoleVO.setRoleIds(roleIds);
        updateUserRoleVO.setRoles(roleVo);
        updateUserRoleVO.setUser(userDto);

        return ResponseResult.okResult(updateUserRoleVO);
    }

    /**
     * @description 更新用户信息
     * @param dto
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @author 31115
     * @date 2022/12/8 10:54
     */
    @Override
    @Transactional
    public ResponseResult updateUser(UpdateUserDto dto) {
        //先删除用户对应角色的id数据
        if (dto.getRoleIds().size() != 0) {
            LambdaQueryWrapper<UserRole> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserRole::getUserId,dto.getId());
            userRoleService.remove(wrapper);
        }
        //更新用户信息
        User user = BeanCopyUtils.beanCopyUtils(dto, User.class);
        updateById(user);

        //插入用户角色数据
        try {
            List<Long> roleIds = dto.getRoleIds();
            List<UserRole> userRoles = roleIds.stream()
                    .map(new Function<Long, UserRole>() {
                        @Override
                        public UserRole apply(Long roleId) {
                            UserRole userRole = new UserRole();
                            userRole.setUserId(user.getId());
                            userRole.setRoleId(roleId);
                            return userRole;
                        }
                    }).collect(Collectors.toList());
            userRoleService.saveBatch(userRoles);
        } catch (Exception e) {
            log.info("用户角色数据修改一场 {} ",e);
        }

        return ResponseResult.okResult();
    }

    /**
     * @description 修改用户状态
     * @param dto
     * @return com.zhangzhan.domain.commcon.ResponseResult
     * @author 31115
     * @date 2022/12/8 11:16
     */
    @Override
    public ResponseResult changeStatus(UserChangeStatusDto dto) {
        //查询当前用户
        User user = getById(dto.getUserId());
        //修改状态
        user.setStatus(dto.getStatus());
        updateById(user);
        return ResponseResult.okResult();
    }
}

